const chokidar = require('chokidar');
const { join } = require('path');
const fs = require('fs');

const registry = {};
const rootDir = join(__dirname, '../services/');

function checkAndRegisterModule(m, path, oper) {
  let errorCount = 0;
  if (m.path !== path) {
    errorCount += 1;
    console.warn(`文件路径${path}和 exports.path(${m.path}) 不一致`);
  }
  // 检查必要属性是否齐全
  if (!m.title) {
    errorCount += 1;
    console.warn(`${path} 没有 title`);
  }
  // 检查必要属性是否齐全
  m.sqltext = m.sqltext || m.sql; // 写成 sql 或者 sqltext 都行
  if (!m.sqltext) {
    try {
      m.sqltext = fs.readFileSync(`${rootDir + path}.sql`, { encoding: 'utf8' });
    } catch (e) {
      errorCount += 1;
      console.warn(`${path} 没有 sqltext`);
    }
  }
  if (errorCount === 0) {
    registry[path] = m;
    console.log(`${oper} ${path}`);
  }
}

chokidar.watch(rootDir, {
  cwd: rootDir,
  disableGlobbing: false,
  depth: 5,
  awaitWriteFinish: true,
}).on('all', (event, path) => {
  // console.log(event, path);
  if (!path.match(/\.(js|sql)$/)) return;
  const requirePath = rootDir + path;
  const registryKey = `/${path.replace(/\.(js|sql)$/, '').replace(/\\/g, '/')}`;
  let atomService;
  let absPath;
  if (path.match(/\.sql$/)) {
    atomService = registry[registryKey];
    if (!atomService) return;
    fs.readFile(requirePath, { encoding: 'utf8' }, (err, sql) => { atomService.sqltext = sql; });
    return;
  }

  switch (event) {
    case 'add':
      try {
        atomService = require(requirePath);
      } catch (e) {
        console.error('module init hot reload error', path, e);
        return;
      }
      checkAndRegisterModule(atomService, registryKey, 'register');
      break;
    case 'change':
      absPath = require.resolve(requirePath);
      if (absPath) {
        delete require.cache[absPath];
      } else {
        console.log('no absPath');
      }
      try {
        atomService = require(requirePath);
      } catch (e) {
        console.error('module change hot reload error', path, e);
        return;
      }
      checkAndRegisterModule(atomService, registryKey, 'upgrade');
      break;
    case 'unlink':
      absPath = require.resolve(requirePath);
      if (absPath) {
        delete require.cache[absPath];
      } else {
        console.log('no absPath');
      }
      delete registry[registryKey];
      break;
    default:
  }
});


// setTimeout(() => console.log(Object.keys(registry)), 3000);

exports.registry = registry;
